#include "mymqtt.h"

MyMqtt::MyMqtt(QString hst, quint16 prt, QString usr, QString pass, QObject *parent)
    : QObject{parent}
{
    userPassword = pass;
    userName = usr;
    hostName = hst;
    port = prt;

    this->initMqttClient();
    this->connectToBroker();
}

void MyMqtt::initMqttClient()
{
    mqttClient = new QMqttClient(this);
    // rcvParser = new RcvParserMQTT(this);
    mqttClient->setUsername(userName);
    mqttClient->setPassword(userPassword);

    mqttClient->setHostname(hostName);
    mqttClient->setPort(port);
    mqttClient->setKeepAlive(2);
    mqttClient->setAutoKeepAlive(true);

    connect(mqttClient, &QMqttClient::stateChanged, this, &MyMqtt::updateStateChange);
    connect(mqttClient, &QMqttClient::disconnected, this, &MyMqtt::brokerDisconnected);
    // connect(mqttClient, &QMqttClient::keepAliveChanged, this, &DetectorMQTT::keepAliveChange);
    connect(mqttClient, &QMqttClient::pingResponseReceived, this, &MyMqtt::keepAliveChange);
    // connect(mqttClient, &QMqttClient::messageReceived, this, [this](const QByteArray &message, const QMqttTopicName &topic) {
    //     const QString content = QDateTime::currentDateTime().toString()
    //                             + " Received Topic: "
    //                             + topic.name()
    //                             + " Message: "
    //                             + message
    //                             + u'\n';
    //     qDebug() << "DetectorMQTT: received topic" << content;
    // });

    connect(mqttClient, &QMqttClient::messageReceived, this, &MyMqtt::getMessage);
    // connect(rcvParser, SIGNAL(newSettingsReceived(DETECTOR_MODE,const QByteArray&)),this, SIGNAL(newSettingsReceived(DETECTOR_MODE,const QByteArray&)));
    // connect(rcvParser, SIGNAL(newModeSet(DETECTOR_MODE)),this, SIGNAL(newModeReceived(DETECTOR_MODE)));
    // connect(rcvParser, SIGNAL(sendError(QString&, QByteArray&)),this, SLOT(publishData(QString&,QByteArray&)));

    tryConnecting = new QTimer(this);
    tryConnecting->setInterval(1500);
    connect(tryConnecting, &QTimer::timeout, this, &MyMqtt::sendPing);
}

TOPICS MyMqtt::getTopicsNum(QString topicReceived)
{
    if (TOPICS_MAP.contains(topicReceived)) {
        return TOPICS_MAP.value(topicReceived);
    } else {
        return TOPICS::NONE;
    }
}

float MyMqtt::convertByteArrayToFloat(QByteArray data)
{
    return *reinterpret_cast<float*>(data .data());
}

void MyMqtt::parseArrayData(const QByteArray &message)
{
    arrayData.clear();

    auto size = message.size() / 4;
    arrayData.resize(size);

    for (uint32_t i = 0; i < size; i++) {
        // qDebug() << i << message.sliced(i, 4) << convertByteArrayToFloat(message.sliced(i, 4));
        arrayData[i] = convertByteArrayToFloat(message.sliced(i*4, 4));
    }

    // qDebug() << arrayData;
    emit arrayDataReceived(arrayData);
}

void MyMqtt::updateStateChange(QMqttClient::ClientState state)
{
    qDebug() << "DetectorMQTT::state changed" << state;
    QByteArray data = "1, 2, 3";
    switch (state) {
    case QMqttClient::Disconnected:

        break;
    case QMqttClient::Connected:
        tryConnecting->stop();
        this->setSubscription(VIDEO_TOPIC);
        this->setSubscription(SPECTR_TOPIC);
        this->setSubscription(LORA_TOPIC);
        //test
        // this->publishData(videoTopic, data);
        break;
    case QMqttClient::Connecting:

        break;
    }
}

void MyMqtt::setSubscription(QString &topic)
{
    auto subscription = mqttClient->subscribe(topic);
    if (!subscription) {
        qDebug() << "DetectorMQTT : Subscribe Error";
        return;
    }
}

void MyMqtt::brokerDisconnected()
{
    qDebug() << "DetectorMQTT::broker disconnected";
    if (mqttClient->state() == QMqttClient::Disconnected){
        // mqttClient->setAutoKeepAlive(false);
        tryConnecting->start();
    }
}

void MyMqtt::keepAliveChange()
{
    qDebug() << "DetectorMQTT::keepAlive";
        // if (mqttClient->state() == QMqttClient::Disconnected){
        //     mqttClient->connectToHost();
        // }
}

void MyMqtt::sendPing()
{
    qDebug() << "DetectorMQTT::try connecting";
    mqttClient->connectToHost();
    tryConnecting->start();
}

void MyMqtt::connectToBroker()
{
    if (mqttClient->state() == QMqttClient::Disconnected) {
        mqttClient->connectToHost();
    } else {
        mqttClient->disconnectFromHost();
    }
}

void MyMqtt::publishData(QString &topic, QByteArray &data)
{

}

void MyMqtt::getMessage(const QByteArray &message, const QMqttTopicName &topic)
{
    qDebug() << topic;
    auto curTopic = getTopicsNum(topic.name());

    switch (curTopic) {
    case TOPICS::SPECTR:
        this->parseArrayData(message);
        break;
    case TOPICS::NONE:

        break;
    }
}
